#region Using directives

using System;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;
using System.Text;

#endregion

namespace Ndo
{
    public sealed class ReaderAttribute : Attribute
    { };
    public sealed class WriterAttribute : Attribute
    { };
    public interface IRWSynchronized<T> : IBoxed<T>
    {
        ReaderWriterLock Locker { get;}
    }
    public static class RWSynchronize<T>
        where T : class
    {
        public static T From(T target)
        {
            return From(target, new ReaderWriterLock());
        }
        public static T From(T target, ReaderWriterLock locker)
        {
            if (target == null || locker == null)
                throw new ArgumentNullException();
            return (T)CI.Invoke(new object[] { target, locker });
        }
        static readonly ConstructorInfo CI;

        static RWSynchronize()
        {
            CI = new RWSynchronizeFactory<T>(
                string.Format("RWSynchronize[{0}]{1}",
                typeof(T).FullName, BoxHelper.GetId())).CI;
        }
        public static ReaderWriterLock GetLocker(T boxedObj)
        {
            if (!(boxedObj is IRWSynchronized<T>))
                throw new InvalidOperationException();
            return ((IRWSynchronized<T>)boxedObj).Locker;
        }
        public static T GetTarget(T boxedObj)
        {
            if (!(boxedObj is IRWSynchronized<T>))
                throw new InvalidOperationException();
            return ((IRWSynchronized<T>)boxedObj).Target;
        }
    }
}
